package cn.ffcs.utils;

import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* 实现了一个FTPClient连接池
* @author heaven
*/
@Slf4j
@Component
public class FtpClientPool implements ObjectPool<FTPClient>, InitializingBean {

    @Value("${ftp.threadNum}")
    private Integer DEFAULT_POOL_SIZE;

    private BlockingQueue<FTPClient> pool;

    @Autowired
    private FtpClientFactory ftpClientFactory;

    /**
     * 初始化连接池，需要注入一个工厂来提供FTPClient实例
     *
     * @param maxPoolSize
     * @throws Exception
     */
    public void initPool(int maxPoolSize) throws Exception {
        pool = new ArrayBlockingQueue<FTPClient>(DEFAULT_POOL_SIZE * 2);
        for (int i = 0; i < maxPoolSize; i++) {
            //往池中添加对象
            addObject();
        }
    }


    public FTPClient borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
        FTPClient client = pool.take();
        if (client == null) {
            client = ftpClientFactory.makeObject();
            addObject();
        } else if (!ftpClientFactory.validateObject(client)) {//验证不通过
            //使对象在池中失效
            invalidateObject(client);
            //制造并添加新对象到池中
            client = ftpClientFactory.makeObject();
            //addObject();
        }
        log.info("borrow success, ftp pool size : " + pool.size());
        return client;

    }

    public void returnObject(FTPClient client) throws Exception {
        if ((client != null) && !pool.offer(client, 3, TimeUnit.SECONDS)) {
            try {
                ftpClientFactory.destroyObject(client);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            log.info("return success, ftp pool size : " + pool.size());
        }

    }

    public void invalidateObject(FTPClient client) throws Exception {
        //移除无效的客户端
        pool.remove(client);
    }


    public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
        //插入对象到队列
        if(pool.size() < DEFAULT_POOL_SIZE) {
            FTPClient client = ftpClientFactory.makeObject();
            if(client != null) {
                pool.offer(client, 3, TimeUnit.SECONDS);
                log.info("add object success,ftp pool size:" + pool.size());
            }
        }
    }

    public int getNumIdle() throws UnsupportedOperationException {
        return 0;
    }

    public int getNumActive() throws UnsupportedOperationException {
        return 0;
    }

    public void clear() throws Exception, UnsupportedOperationException {

    }

    public void close() throws Exception {
        while (pool.iterator().hasNext()) {
            FTPClient client = pool.take();
            ftpClientFactory.destroyObject(client);
        }
    }

    public void setFactory(PoolableObjectFactory<FTPClient> factory) throws IllegalStateException, UnsupportedOperationException {

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initPool(DEFAULT_POOL_SIZE);
    }
}
